#####################################################################
#                                                                   #
#  THIS IS A SOURCE CODE FILE FROM A PROGRAM TO INTERACT WITH THE   #
# LBRY PROTOCOL ( lbry.com ). IT WILL USE THE LBRY SDK ( lbrynet )  #
# FROM THEIR REPOSITORY ( https://github.com/lbryio/lbry-sdk )      #
# WHICH I GONNA PRESENT TO YOU AS A BINARY. SINCE I DID NOT DEVELOP #
# IT AND I'M LAZY TO INTEGRATE IN A MORE SMART WAY. THE SOURCE CODE #
# OF THE SDK IS AVAILABLE IN THE REPOSITORY MENTIONED ABOVE.        #
#                                                                   #
#      ALL THE CODE IN THIS REPOSITORY INCLUDING THIS FILE IS       #
# (C) J.Y.Amihud and Other Contributors 2021. EXCEPT THE LBRY SDK.  #
# YOU CAN USE THIS FILE AND ANY OTHER FILE IN THIS REPOSITORY UNDER #
# THE TERMS OF GNU GENERAL PUBLIC LICENSE VERSION 3 OR ANY LATER    #
# VERSION. TO FIND THE FULL TEXT OF THE LICENSE GO TO THE GNU.ORG   #
# WEBSITE AT ( https://www.gnu.org/licenses/gpl-3.0.html ).         #
#                                                                   #
# THE LBRY SDK IS UNFORTUNATELY UNDER THE MIT LICENSE. IF YOU ARE   #
# NOT INTENDING TO USE MY CODE AND JUST THE SDK. YOU CAN FIND IT ON #
# THEIR OFFICIAL REPOSITORY ABOVE. THEIR LICENSE CHOICE DOES NOT    #
# SPREAD ONTO THIS PROJECT. DON'T GET A FALSE ASSUMPTION THAT SINCE #
# THEY USE A PUSH-OVER LICENSE, I GONNA DO THE SAME. I'M NOT.       #
#                                                                   #
# THE LICENSE CHOSEN FOR THIS PROJECT WILL PROTECT THE 4 ESSENTIAL  #
# FREEDOMS OF THE USER FURTHER, BY NOT ALLOWING ANY WHO TO CHANGE   #
# THE LICENSE AT WILL. SO NO PROPRIETARY SOFTWARE DEVELOPER COULD   #
# TAKE THIS CODE AND MAKE THEIR USER-SUBJUGATING SOFTWARE FROM IT.  #
#                                                                   #
#####################################################################


# This file will contain elements used a lot with in the application.
# They are all built upon GTK, so it's implementable without using these
# but it may simplify your modification. Since the elements in will be
# specific to making something like this application easier.

import os
import urllib.request
import threading
import json
from subprocess import *
from gi.repository import Gtk
from gi.repository import Gio
from gi.repository import Gdk
from gi.repository import Pango
from gi.repository import GdkPixbuf
from PIL import Image, ImageSequence

def icon( win, name, f="png"):

    # This function returns an icon of the current setting, or a
    # system default icon if there is no such icon in the set icon theme.
    # For this, of course, we will need to store names of what those
    # icons are called in the system. Not everthing is the same.
    
    # I could name the icons in the custom theme the same way, but
    # this would require using some hilarious names.
    
    system_names = {
        "settings":"application-menu",
        "connect":"network-connect",
        "disconnect":"network-disconnect",
        "loading":"accept_time_event",
        "launch":"player_play"
    }
    

    try_icon = "icons/"+win.settings["GTK_icon_theme"]+"/"+name+"."+f
    
    if os.path.exists(try_icon):
        return Gtk.Image.new_from_file(try_icon)
    else:
        # Real GTK Spinner for loading ? Why not?
        if name == "loading":
            s = Gtk.Spinner()
            s.set_size_request(64,64)
            s.start()
            return s
        except_icon = Gio.Icon.new_for_string(system_names.get(name, name))
        return Gtk.Image.new_from_gicon(except_icon, Gtk.IconSize.DND)

def resize_gif(filename, new_file, size):

    # This function will resize a gif

    gif = Image.open(filename)
    layers = ImageSequence.Iterator(gif)

    def rs(l):
        for i in l:
            rsv = i.copy()
            rsv.thumbnail(size, Image.ANTIALIAS)
            yield rsv
    layers = rs(layers)

    # Overwrite the original gif
    f = next(layers)
    f.info = gif.info
    f.save(new_file, save_all=True, append_images=list(layers))
    
def load(win, widget_function, *args):

    # This function will load widgets that take time to load.
    # It will show a spinner while the widget is loading. And when
    # the widget_function will return a finished widget, it will
    # swap the spinner for the final widget.

    wbox = Gtk.HBox()
    widget = icon(win, "loading", "gif")
    wbox.pack_start(widget, True, True, True)

    def resolve_widget_thread(widget, wbox, wf, *args):
        new_widget = wf(*args)
        widget.destroy()
        wbox.pack_start(new_widget, True, True, True)
        #wbox.show_all()
        win.show_all()
        
        
    load_thread = threading.Thread(target=resolve_widget_thread, args=(widget, wbox, widget_function, *args))
    load_thread.setDaemon(True)
    load_thread.start()
    

    return wbox

def net_image( url, size, save_as, allow_gif):

    ret = Gtk.Image()
    
    delete = False
    if not save_as:
        delete = True
        good = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOOPASDFGHJKLZXCVBNM_"
        for i in url:
            if i in good:
                save_as = save_as + i
            else:
                save_as = save_as + "_"
        save_as = "/tmp/"+save_as
    
    # This function will load the image in a separate thread.
    try:
        urllib.request.urlretrieve(url, save_as)
    except Exception as e:
        f = open(save_as, "w")
        f.close()

    if size:
        try:
            
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(save_as, size, size)
            ret = Gtk.Image.new_from_pixbuf(pixbuf)
        except:
            try:

                os.rename(save_as, save_as+".gif")
                resize_gif(save_as+".gif", save_as+"_2.gif", [size,size])
                ret = Gtk.Image.new_from_file(save_as+"_2.gif")
                os.remove(save_as+"_2.gif")
                os.rename(save_as+".gif", save_as)
                
            except Exception as e:
                print("GIF RESIZING ERROR", e)
                if allow_gif:
                    ret = Gtk.Image.new_from_file(save_as)
    else:
        ret = Gtk.Image.new_from_file(save_as)
        
    if delete:
        try:
            os.remove(save_as)
        except:
            pass
        
    return ret
